package com.wsoft.cms.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wsoft.cms.entity.CmsAnnouncementEntity;
import com.wsoft.cms.entity.CmsAnnouncementFileEntity;
import com.wsoft.cms.entity.CmsAnnouncementSummaryEntity;
import com.wsoft.cms.enums.AnnoReadEnum;
import com.wsoft.cms.mapper.CmsAnnouncementMapper;
import com.wsoft.cms.query.announcement.AnnouncementListQuery;
import com.wsoft.cms.vo.anno.AnnouncementInfoVO;
import com.wsoft.cms.vo.anno.AnnouncementListVO;
import com.wsoft.cms.vo.anno.AnnouncementVO;
import com.wsoft.cms.vo.category.CmsCategoryInfoVO;
import com.wsoft.cms.vo.summary.SummaryVO;
import com.wsoft.constant.redis.RedisKeyConstant;
import com.wsoft.core.annotation.GetRedisCache;
import com.wsoft.core.service.CommonMemberService;
import com.wsoft.core.service.CommonOrgService;
import com.wsoft.core.service.RedisService;
import com.wsoft.core.utils.LoginUserUtil;
import com.wsoft.core.vo.OrganizationVO;
import com.wsoft.entity.BaseEntity;
import com.wsoft.enums.DeviceEnum;
import com.wsoft.enums.MsgTypeEnum;
import com.wsoft.enums.PublishStatusEnum;
import com.wsoft.vo.LoginUserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author z001
 * @Date 2024/11/27 10:42
 */
@Slf4j
@Service
public class CmsAnnouncementManager extends ServiceImpl<CmsAnnouncementMapper, CmsAnnouncementEntity> {

    @Resource
    private RedisService redisService;
    @Resource
    private CmsCategoryManager categoryManager;
    @Resource
    private CommonMemberService memberService;
    @Resource
    private CommonOrgService orgService;
    @Resource
    private CmsAnnouncementFileManager fileManager;
    @Resource
    private CmsAnnouncementSummaryManager summaryManager;
    @Resource
    private CmsAnnouncementReadManager readManager;

    /**
     * 根据id获取
     *
     * @param annoId
     * @return
     */
    public AnnouncementVO getAnnoInfoById(CmsAnnouncementEntity entity) {
        AnnouncementVO resultVo = new AnnouncementVO();
        Long annoId = entity.getId();
        //文章基础信息
        AnnouncementInfoVO convert = Convert.convert(AnnouncementInfoVO.class, entity);
        if (Objects.equals(entity.getSendStatus(), PublishStatusEnum.PUBLISH.getType())) {
            convert.setSendMemberName(memberService.getMemberInfo(convert.getSendMemberId()).getName());
            convert.setSendOrgName(orgService.getOrgInfo(convert.getSendOrgId()).getName());
        } else {
            convert.setSendMemberName("");
            convert.setSendOrgName("");
        }
        convert.setCategoryName(categoryManager.getById(convert.getCategoryId()).getName());

        resultVo.setAnnoInfo(convert);

        //分类信息
        CmsCategoryInfoVO categoryInfoVO = categoryManager.getById(entity.getCategoryId());
        resultVo.setCategoryInfo(categoryInfoVO);

        //文章附件信息
        List<CmsAnnouncementFileEntity> fileEntityList = fileManager.getByAnnoId(annoId);
        resultVo.setFileInfo(new ArrayList<>());
        if (CollUtil.isNotEmpty(fileEntityList)) {
            List<String> collect = fileEntityList.stream().map(CmsAnnouncementFileEntity::getFile).collect(Collectors.toList());
            resultVo.setFileInfo(collect);
        }

        //summary信息
        resultVo.setSummary(Convert.convert(SummaryVO.class, summaryManager.getById(annoId)));
        return resultVo;
    }


    /**
     * 根据id 修改
     *
     * @param entity
     * @return
     */
    @Override
    public boolean updateById(CmsAnnouncementEntity entity) {
        boolean b = super.updateById(entity);
        if (b) {
            redisService.del(RedisKeyConstant.Cms.CMS_ANNO_INFO + entity.getId());
        }
        return b;
    }

    /**
     * 批量跟新
     * @param list
     * @return
     */
    public boolean updateBatchById(List<CmsAnnouncementEntity> list){
        boolean b = super.updateBatchById(list);
        if(b){
            for (CmsAnnouncementEntity commentEntity : list) {
                redisService.del(RedisKeyConstant.Cms.CMS_ANNO_INFO + commentEntity.getId());
            }
        }
        return b;
    }

    /**
     * 查询公告列表 并组装相关数据
     *
     * @param listQuery
     * @param isUser
     * @return
     */
    public PageInfo listAnno(AnnouncementListQuery listQuery, boolean isUser) {
        PageHelper.startPage(listQuery.getPageNum(), listQuery.getPageSize());
        List<CmsAnnouncementEntity> list = listAnnoQuery(listQuery, isUser, null);
        PageInfo pageInfo = PageInfo.of(list);
        list = pageInfo.getList();
        List<AnnouncementListVO> collect = list.stream().map(item -> Convert.convert(AnnouncementListVO.class, item)).collect(Collectors.toList());
        for (AnnouncementListVO announcementVO : collect) {
            CmsAnnouncementSummaryEntity summary = summaryManager.getById(announcementVO.getId());
            announcementVO.setCommentNum(summary == null ? 0 : summary.getCommentNum());
            announcementVO.setViewNum(summary == null ? 0 : summary.getViewNum());
            announcementVO.setSignNum(summary == null ? 0 : summary.getSignNum());
        }
        pageInfo.setList(collect);
        return pageInfo;
    }

    /**
     * 查询公告列表
     *
     * @param listQuery
     * @param isUser
     * @return
     */
    public List<CmsAnnouncementEntity> listAnnoQuery(AnnouncementListQuery listQuery, boolean isUser, Long annoId) {
        QueryWrapper<CmsAnnouncementEntity> query = new QueryWrapper<>();
        if(null != listQuery.getIsRead() && !listQuery.getIsRead().equals(AnnoReadEnum.ALL.getType())){
            //有已读搜索条件
            Set<Long> readAnno = readManager.getByMemberId(LoginUserUtil.getUserInfo().getLoginUserVO().getId());
            //已读
            if(Objects.equals(listQuery.getIsRead(), AnnoReadEnum.READ.getType())){
                query.lambda().in(BaseEntity::getId, readAnno);
            }else{
                //未读
                query.lambda().notIn(BaseEntity::getId, readAnno);
            }
        }

        query.lambda().eq(null != listQuery.getCategoryId(), CmsAnnouncementEntity::getCategoryId, listQuery.getCategoryId())
                .like(StrUtil.isNotBlank(listQuery.getTitle()), CmsAnnouncementEntity::getTitle, listQuery.getTitle())
                .eq(null != listQuery.getSendOrgId(), CmsAnnouncementEntity::getSendOrgId, listQuery.getSendOrgId())
                .eq(StrUtil.isNotBlank(listQuery.getSendStatus()), CmsAnnouncementEntity::getSendStatus, listQuery.getSendStatus())
                .eq(StrUtil.isNotBlank(listQuery.getPriority()), CmsAnnouncementEntity::getPriority, listQuery.getPriority())
                .ge(StrUtil.isNotBlank(listQuery.getSendTimeBegin()), CmsAnnouncementEntity::getSendTime, listQuery.getSendTimeBegin())
                .le(StrUtil.isNotBlank(listQuery.getSendTimeEnd()), CmsAnnouncementEntity::getSendTime, listQuery.getSendTimeEnd());
        if (isUser) {
            //用户端 只查询已发布的,发布时间排序
            query.lambda().eq(CmsAnnouncementEntity::getSendStatus, PublishStatusEnum.PUBLISH.getType());
            query.lambda().eq(CmsAnnouncementEntity::getDevice,StrUtil.isBlank(listQuery.getDevice())? DeviceEnum.WEB.getType():listQuery.getDevice());
            LoginUserVO userVO = LoginUserUtil.getUserInfo().getLoginUserVO();
            //当前登录人组织
            Long curOrgId = userVO.getLoginOrgId();
            //当前登录人岗位
            Long curPostId = userVO.getCurPostId();
            //当前登录人级别
            Long curLevelId = userVO.getLevelId();
            //当前登录人id
            Long curUserId = userVO.getId();

            List<OrganizationVO> parentOrg = orgService.getParentOrg(curOrgId);
            List<Long> orgIdList = new ArrayList<>();
            orgIdList.add(curOrgId);
            if (CollUtil.isNotEmpty(parentOrg)) {
                orgIdList.addAll(parentOrg.stream().map(OrganizationVO::getOrgId).collect(Collectors.toList()));
            }
            //权限
            query.lambda().and(wrapper ->
                    wrapper.nested(nestedWrapper -> {
                        // 指定组织
                        for (Long orgId : orgIdList) {
                            nestedWrapper.or(nestedOrWrapper ->
                                    nestedOrWrapper.eq(CmsAnnouncementEntity::getMsgType, MsgTypeEnum.ORG.getType())
                                            .apply("FIND_IN_SET({0}, msg_ids)", orgId) // 使用 FIND_IN_SET 判断是否包含当前组织 ID
                            );
                        }
                    }).or(nestedWrapper ->
                            //指定岗位
                            nestedWrapper.eq(CmsAnnouncementEntity::getMsgType, MsgTypeEnum.POST.getType())
                                    .like(CmsAnnouncementEntity::getMsgIds, curPostId)
                    ).or(nestedWrapper ->
                            //指定级别
                            nestedWrapper.eq(CmsAnnouncementEntity::getMsgType, MsgTypeEnum.LEVEL.getType())
                                    .like(CmsAnnouncementEntity::getMsgIds, curLevelId)
                    ).or(nestedWrapper ->{
                        //指定用户
                        nestedWrapper.or(nestedOrWrapper ->
                                nestedOrWrapper.eq(CmsAnnouncementEntity::getMsgType, MsgTypeEnum.MEMBER.getType())
                                        .apply("FIND_IN_SET({0}, msg_ids)", curUserId)
                        );
                    })
            );
            query.lambda()
                    .orderByDesc(CmsAnnouncementEntity::getTopTime)
                    .orderByDesc(CmsAnnouncementEntity::getSendTime);
        } else {
            //后台端,an发布状态查询,创建时间排序
            query.lambda().eq(StrUtil.isNotBlank(listQuery.getSendStatus()), CmsAnnouncementEntity::getSendStatus, listQuery.getSendStatus())
                    .orderByDesc(BaseEntity::getCreateTime);
        }
        List<CmsAnnouncementEntity> list = list(query);
        if (null != annoId) {
            //annoId不为空,则判断 ==> 当前是否有权限查看这个anno文章,如果返回有值,则有权限,如果返回list为空,则无权限
            list = list.stream().filter(item -> item.getId().equals(annoId)).collect(Collectors.toList());
        }
        return list;
    }


    /**
     * 删除
     *
     * @param id
     * @return
     */
    public boolean removeById(Long id) {
        boolean b = super.removeById(id);
        if (b) {
            redisService.del(RedisKeyConstant.Cms.CMS_ANNO_INFO + id);
        }
        return b;
    }


    /**
     * 获取当前 待发布的文章
     * @return
     */
    public List<CmsAnnouncementEntity> getPublishAnno(){
        QueryWrapper<CmsAnnouncementEntity> query = new QueryWrapper<>();
        query.lambda().eq(CmsAnnouncementEntity::getSendStatus, PublishStatusEnum.WAIT_PUBLISH.getType())
                .le(CmsAnnouncementEntity::getSendTime, LocalDateTime.now());
        return list(query);
    }

    /**
     * 根据id获取
     *
     * @param annoId
     * @return
     */
    @GetRedisCache(type = RedisKeyConstant.Cms.CMS_ANNO_INFO,
            expire_sec = RedisKeyConstant.Cms.EXPIRED,
            value = RedisKeyConstant.REDIS_SELF)
    public CmsAnnouncementEntity getById(Long annoId) {
        return super.getById(annoId);
    }
}
